package com.authine.cloudpivot.ext.applicationservice;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapBuilder;
import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.Enum.*;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.FinanceReportDto;
import com.authine.cloudpivot.ext.dto.base.Ids;
import com.authine.cloudpivot.ext.dto.base.PageList;
import com.authine.cloudpivot.ext.dto.model.invoice.InvoiceApply;
import com.authine.cloudpivot.ext.dto.model.settle.*;
import com.authine.cloudpivot.ext.dto.model.trade.Trade;
import com.authine.cloudpivot.ext.dto.query.InvoiceQuery;
import com.authine.cloudpivot.ext.dto.query.SettleApplyQuery;
import com.authine.cloudpivot.ext.dto.query.SettleQuery;
import com.authine.cloudpivot.ext.dto.query.TradeQuery;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.service.bill.BillService;
import com.authine.cloudpivot.ext.service.bill.impl.BillServiceImpl;
import com.authine.cloudpivot.ext.service.invoice.InvoiceApplyService;
import com.authine.cloudpivot.ext.service.invoice.impl.InvoiceApplyServiceImpl;
import com.authine.cloudpivot.ext.service.organiztion.OrganizationService;
import com.authine.cloudpivot.ext.service.settle.SettleService;
import com.authine.cloudpivot.ext.service.settle.impl.SettleServiceImpl;
import com.authine.cloudpivot.ext.service.voucher.KingDeeFinanceService;
import com.authine.cloudpivot.ext.service.voucher.impl.KingDeeFinanceServiceImpl;
import com.authine.cloudpivot.ext.utils.*;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.cloudpivot.ext.utils.system.ReportUtils;
import com.authine.cloudpivot.ext.utils.system.SessionUser;
import com.authine.common.json.JsonUtils;
import com.authine.common.util.DateUtils;
import com.authine.common.util.ObjectMapperUtils;
import com.authine.hermes.app.launcher.service.ApplicationService;
import com.authine.mvp.app.launcher.domain.utills.ApplicationContextUtils;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.util.Maps;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StopWatch;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

@Slf4j
@Path("SettleController")
public class SettleController extends ApplicationService {

    NamedParameterJdbcTemplate jdbcTemplate =  ApplicationContextUtils.getBean(NamedParameterJdbcTemplate.class);
    TransactionTemplate transactionTemplate =  ApplicationContextUtils.getBean(TransactionTemplate.class);
    private static BillService billService = new BillServiceImpl();
    private static InvoiceApplyService invoiceApplyService = new InvoiceApplyServiceImpl();
    private static SettleService settleService = new SettleServiceImpl();
    private static OrganizationService organizationService = new OrganizationService();
    private static KingDeeFinanceService kingDeeFinanceService = new KingDeeFinanceServiceImpl();

    /**
     * 结算查询平台销售发票单列表,结算查询平台采购发票单列表,结算查询代购服务费发票单列表 通过query.direction区分是采购还是销售，服务费发票
     * @param query
     * @return
     */
    @Path("settleInvoicePage")
    @POST
    @Operation(summary = "平台采购付款管理-待申请-列表(发票维度)",description = "其余引用部分。供应商收款管理-待申请,平台销售收款管理-代购服务费收款核销-核销",tags = CUSTOM_SERVICE)
    public MultiResponse<InvoiceApply> settleInvoicePage(InvoiceQuery query){

        SessionUser sessionUser = new SessionUser();
        String currentOrgId = sessionUser.getCurrentOrgID();
        if ("Purchase".equals(query.getDirection())){//平台采购付款管理，供应商销售收款管理
            //不是平台
            if (!PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(currentOrgId)) {
                query.setSale_organization_id(Collections.singletonList(currentOrgId));
            }else{
                //如果是平台，并且发票号码和发票抬头搜索条件不为空，则忽略组织的查询条件
                boolean num = null != query.getNumber() && !query.getNumber().trim().isEmpty();
                boolean pname = null != query.getPurchase_name() && !query.getPurchase_name().trim().isEmpty();
                if (num || pname) {
                    query.setSale_organization_id(null);
                }
            }
            if (CollectionUtils.isEmpty(query.getPurchase_organization_id())) {
                query.setPurchase_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS);
            }
            query.setBusiness_type(Collections.singletonList(InvoiceBusinessType.Product.name()))
                    .setStatuss(Collections.singletonList(InvoiceStatus.Done.name()));
            //根据当前用户组织ID获取集团下所有组织ID，销售组织ID
            buildInvoiceQuerySaleOrganizationIds(query);
        }else if("Sale".equals(query.getDirection())){
            query.setSale_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS)
                    .setBusiness_type(Collections.singletonList(InvoiceBusinessType.Product.name()))
                    .setStatuss(Collections.singletonList(InvoiceStatus.Done.name()));
            if (PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(currentOrgId)) {
                boolean num = null != query.getNumber() && !query.getNumber().trim().isEmpty();
                boolean pname = null != query.getPurchase_name() && !query.getPurchase_name().isEmpty();
                if (num || pname) {
                    query.setPurchase_organization_name(null);
                }
            }
            //设置发票的采购组织ID,非平台
            buildInvoiceQueryPurchaseOrganizationIds(query);
        }else if("contract".equals(query.getDirection())){//代购服务费
            query.setSale_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS)
                    .setBusiness_type(Collections.singletonList(InvoiceBusinessType.Service.name()))
                    .setStatuss(Collections.singletonList(InvoiceStatus.Done.name()))
                    .setTradeOrderType(TradeOrderType.Agent.name());
            //如果是平台，并且发票号码和发票抬头搜索条件不为空，则忽略组织的查询条件
            if (PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(currentOrgId)) {
                boolean num = null != query.getNumber() && !query.getNumber().trim().isEmpty();
                boolean pname = null != query.getPurchase_name() && !query.getPurchase_name().isEmpty();
                if (num || pname) {
                    query.setPurchase_organization_name(null);
                }
            }
            buildInvoiceQueryPurchaseOrganizationIds(query);
        }
        query.setOrderBy(" order by confirm_time desc ");
        PageList<InvoiceApply> boList = invoiceApplyService.page(query);
        if(boList.getTotal()>0){
            List<InvoiceApply> invoiceApplyList = boList.getData();
            for (InvoiceApply invoiceApply : invoiceApplyList) {
                //可核销金额=发票金额-发票红冲金额-已核销金额
                BigDecimal writtenOffAmount = invoiceApply.getWritten_off_amount() == null ? BigDecimal.ZERO : invoiceApply.getWritten_off_amount();
                BigDecimal offsetTotal = invoiceApply.getOffset_total() == null ? BigDecimal.ZERO : invoiceApply.getOffset_total();
                BigDecimal writeOffAmount = invoiceApply.getTotal().subtract(offsetTotal).subtract(writtenOffAmount);
                invoiceApply.setWrite_off_amount(writeOffAmount);
                //核销时，可核销金额小于0的发票，必须要重新核销
                if (writeOffAmount.compareTo(BigDecimal.ZERO) == -1) {
                    //本次核销金额=发票金额-发票红冲金额
                    invoiceApply.setWrite_off_amount(invoiceApply.getTotal().subtract(offsetTotal));
                }
                //平台操作采购付款单核销，需要显示平台费，垫资费，费率取原结算单的费率
                List<String> purchaseOrganizationId = query.getPurchase_organization_id();
                if (null != query.getSettle_id() && "Purchase".equals(query.getDirection()) && PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(purchaseOrganizationId)) {
                    //TODO 计算平台费，垫资费
                }
                //如果是采购付款，要判断是否小规模供应商
                if("Purchase".equals(query.getDirection())){
                    //根据交易客户组织ID获取对应结算组织 判断是否为小规模纳税人
                    OrganizationDto transactionOrganiztion = organizationService.getTransactionOrganiztionId(invoiceApply.getSale_organization_id().getId());
                    if (null != transactionOrganiztion) {
                        invoiceApply.setSmallscale(transactionOrganiztion.getSmall_scale() ? "是":"否");
                    }
                }
            }
            return MultiResponse.of(invoiceApplyList, boList.getTotal());
        }
        return MultiResponse.buildSuccess();
    }

    private void buildInvoiceQueryPurchaseOrganizationIds(InvoiceQuery query) {
        SessionUser sessionUser = new SessionUser();
        if (!sessionUser.isPm()) {
            List<OrganizationDto> orgList = OrgUtils.getOrgListByOrgId(sessionUser.getCurrentOrgID());
            List<String> orgIds = orgList.stream().map(OrganizationDto::getId).collect(Collectors.toList());

            query.setPurchase_organization_id(orgIds);
        } else {
            //查询该组织的父组织所有的子组织
            Collection<String> selectedPurchaseOrganizationIds = query.getPurchase_organization_id();
            if (null != selectedPurchaseOrganizationIds && selectedPurchaseOrganizationIds.size() == 1) {
                Collection<String> purchaseOrganizationIdCollection = query.getPurchase_organization_id();
                Iterator<String> iterator = purchaseOrganizationIdCollection.iterator();
                String purchaseOrganizationId = "";
                while (iterator.hasNext()) {
                    purchaseOrganizationId = iterator.next();
                }
                List<OrganizationDto> orgList = OrgUtils.getOrgListByOrgId(purchaseOrganizationId);
                List<String> orgIds = orgList.stream().map(OrganizationDto::getId).collect(Collectors.toList());

                query.setPurchase_organization_id(orgIds);
            }
        }
    }
    private void buildInvoiceQuerySaleOrganizationIds(InvoiceQuery query) {
        SessionUser sessionUser = new SessionUser();
        if (!sessionUser.isPm()) {
            List<OrganizationDto> orgList = OrgUtils.getOrgListByOrgId(sessionUser.getCurrentOrgID());
            List<String> orgIds = orgList.stream().map(OrganizationDto::getId).collect(Collectors.toList());

            query.setSale_organization_id(orgIds);
        } else {
            //查询该组织的父组织所有的子组织
            Collection<String> selectedSaleOrganizationIds = query.getSale_organization_id();
            if (null != selectedSaleOrganizationIds && selectedSaleOrganizationIds.size() == 1) {
                Collection<String> saleOrganizationIdCollection = query.getSale_organization_id();
                Iterator<String> iterator = saleOrganizationIdCollection.iterator();
                String saleOrganizationId = "";
                while (iterator.hasNext()) {
                    saleOrganizationId = iterator.next();
                }
                List<OrganizationDto> orgList = OrgUtils.getOrgListByOrgId(saleOrganizationId);
                List<String> orgIds = orgList.stream().map(OrganizationDto::getId).collect(Collectors.toList());

                query.setSale_organization_id(orgIds);
            }
        }
    }

    /**
     * 平台采购付款管理，待申请-订单维度查询
     * @return
     */
    @Path("settleOrderPage")
    @POST
    @Operation(summary = "平台采购付款管理-待申请-订单维度查询",description = "平台采购付款管理-待申请-订单维度查询", tags = CUSTOM_SERVICE)
    public MultiResponse<Trade> settleOrderPage(TradeQuery query){
        if (null == query) {
            query = TradeQuery.builder().build();
        }
        //TODO 权限完成后放开
//        SessionUser sessionUser = new SessionUser();
//        Assert.isTrue(PlatformConst.PLATFORM_ORGANIZATION_IDS.contains(sessionUser.getCurrentOrgID()), "订单维度查看平台采购付款管理待申请只有平台权限才能查看");
        if (CollectionUtils.isEmpty(query.getPlatform_organization_id())) {
            query.setPlatform_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS);
        }
        MapBuilder<String, Object> mapBuilder = MapBuilder.create(new HashMap<>());
        StringBuffer sql = new StringBuffer("select trade.vendor_order_id, trade.customer_order_id,GROUP_CONCAT(DISTINCT apply.NUMBER, ',' ) invoice_number,trade.settle_ids settle_ids,")
                .append(" trade.organization_id, trade.organization_name, trade.member_name, SUM(trade.amount) amount, trade.createdTime ")
                .append(" from  ")
                .append(JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_DETAIL)).append(" as detail_bill ")
                .append(" left join ").append(JdbcTemplateUtils.getTableName(ModelConst.T_TRADE)).append(" as trade ON detail_bill.trade_id = trade.ID ")
                .append("\n left join ")
                .append("\n   (SELECT detail.invoice_detail_bill_id invoice_detail_bill_id, SUM(detail.total) total")
                .append("   FROM "+JdbcTemplateUtils.getTableName(ModelConst.T_SETTLE_DETAIL)+" detail LEFT JOIN "+JdbcTemplateUtils.getTableName(ModelConst.T_SETTLE)+" settle ON settle.ID = detail.settle_id ")
                .append("   WHERE settle.STATUS <> 'Returned' GROUP BY detail.invoice_detail_bill_id ) as settle_detail").append(" ON settle_detail.invoice_detail_bill_id = detail_bill.id")
                .append("\n left join ").append(JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_APPLY)).append(" as apply ON detail_bill.invoice_apply_id = apply.ID ")
                .append("\n left join ").append("( SELECT target_order_goods_id, direction, settle_status from ").append(JdbcTemplateUtils.getTableName(ModelConst.T_TRADE)).append(") as targetTrade")
                .append("  ON targetTrade.target_order_goods_id = trade.order_goods_id AND targetTrade.direction = 'Purchase' ")
                .append("\n WHERE ")
                .append("\n (( settle_detail.invoice_detail_bill_id IS NULL OR settle_detail.total < detail_bill.total ) AND apply.statuss = 'Done' AND trade.settle_status <> 'Done' ) ")
                .append(" AND trade.direction = 'Purchase' ");
        if(StringUtils.isNotBlank(query.getInvoice_number())){//发票号码
            sql.append(" and number like :invoiceNumber");
            mapBuilder.put("invoiceNumber", "%".concat(query.getInvoice_number()).concat("%"));
        }
        if(StringUtils.isNotBlank(query.getInvoice_status())){//开票状态
            sql.append(" and trade.invoice_status = :invoiceStatus");
            mapBuilder.put("invoiceStatus", query.getInvoice_status());
        }
        if(StringUtils.isNotBlank(query.getCustomer_order_id())){//客户订单编号
            sql.append(" and trade.customer_order_id = :customer_order_id");
            mapBuilder.put("customer_order_id", query.getCustomer_order_id());
        }
        if(StringUtils.isNotBlank(query.getVendor_order_id())){//供应商订单编号
            sql.append(" and trade.vendeor_order_id = :vendeor_order_id");
            mapBuilder.put("vendeor_order_id", query.getVendor_order_id());
        }
        if(StringUtils.isNotBlank(query.getOrganization_name())){//组织名称
            sql.append(" and trade.organization_name like :organization_name");
            mapBuilder.put("organization_name", query.getOrganization_name());
        }
        if(!CollectionUtils.isEmpty(query.getPlatform_organization_id())){//平台组织ID
            sql.append(" and JSON_UNQUOTE(trade.platform_organization_id ->'$.id') in (:platform_organization_id)");
            mapBuilder.put("platform_organization_id", query.getPlatform_organization_id());
        }
        if(!CollectionUtils.isEmpty(query.getCreatedTime())){
            sql.append(" and trade.createdTime between :start and :end");
            mapBuilder.put("start", query.getCreatedTime().get(0));
            mapBuilder.put("end", query.getCreatedTime().get(1));
        }
        sql.append(" GROUP BY trade.customer_order_id,trade.vendor_order_id,trade.organization_id,trade.organization_name,trade.member_name, DATE_FORMAT(trade.createdTime,'%Y-%m-%d') ");
        String countSql = "select count(1) from ("+sql+") as temp";
        log.info("SettleOrderPage：countSql = {}, parameters = {}", countSql, JSONObject.toJSONString(mapBuilder.build()));
        Integer count = jdbcTemplate.queryForObject(countSql,mapBuilder.build(), Integer.class);
        if(count == 0){
            return MultiResponse.of(null,0);
        }
        sql.append(" order by trade.vendor_order_id desc ");
        String limit = String.format(" limit %s,%s", (query.getPageIndex() - 1) * query.getPageSize(), query.getPageSize());
        sql.append(limit);
        log.info("SettleOrderPage：dataSql = {}, parameters = {}", sql, JSONObject.toJSONString(mapBuilder.build()));
        List<Trade> trades = JdbcTemplateUtils.queryForPOJOList(sql.toString(), mapBuilder.build(), ModelConst.T_TRADE,Trade.class);
        return MultiResponse.of(trades, count);
    }

    /**
     * 平台采购付款管理，待申请-交易维度查询
     * @return
     */
    @Path("settleTradePage")
    @POST
    @Operation(summary = "平台采购付款管理-待申请-交易维度查询",description = "平台采购付款管理-待申请-交易维度查询", tags = CUSTOM_SERVICE)
    public MultiResponse<Trade> settleTradePage(TradeQuery query){
        SessionUser sessionUser = new SessionUser();
        Assert.isTrue(sessionUser.isPm(), "订单维度查看平台采购付款管理待申请只有平台权限才能查看");
        if (CollectionUtils.isEmpty(query.getPlatform_organization_id())) {
            query.setPlatform_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS);
        }
        MapBuilder<String, Object> mapBuilder = MapBuilder.create(new HashMap<>());
        String sql = buildTradeQuerySql(query, mapBuilder);
        String countSql = "select count(1) from ("+sql+") temp";
        log.info("SettleTradePage：countSql = {}, parameters = {}", countSql, JSONObject.toJSONString(mapBuilder.build()));
        Integer count = jdbcTemplate.queryForObject(countSql, mapBuilder.build(), Integer.class);
        if (count == 0){
            return MultiResponse.of(null, 0);
        }
        String limit = String.format(" limit %s,%s", (query.getPageIndex() - 1) * query.getPageSize(), query.getPageSize());
        StringBuffer groupOrder = new StringBuffer(" group by ")
                .append(" detail_bill.trade_id,apply.ID,trade.customer_order_id,")
                .append(" trade.vendor_order_id,trade.order_goods_id,trade.settle_status,trade.organization_id,trade.organization_name,")
                .append(" trade.summary,trade.direction,trade.platform_rate,trade.interest_rate,trade.other_rate,")
                .append(" trade.settle_ids,trade.allowed_settle_amount,trade.platform_organization_id,trade.platform_organization_name,")
                .append(" targetTrade.settle_status,targetTrade.payment_type ")
                .append(" order by detail_bill.trade_id desc ")
                .append(limit);
        sql = sql + groupOrder;
        log.info("SettleTradePage：dataSql = {}, parameters = {}", sql, JSONObject.toJSONString(mapBuilder.build()));
        List<Trade> tradeList = JdbcTemplateUtils.queryForPOJOList(sql,mapBuilder.build(), ModelConst.T_TRADE, Trade.class);
        for (Trade trade : tradeList){
            OrganizationDto organizationDto = OrgUtils.getOrgByOrgId(trade.getOrganization_id().getId());
            trade.setSmall_scale(organizationDto.getSmall_scale());
        }
        return MultiResponse.of(tradeList, count);

    }

    private String buildTradeQuerySql(TradeQuery query, MapBuilder<String, Object> mapBuilder) {
        StringBuffer sql = new StringBuffer("SELECT detail_bill.trade_id AS ID, ")
                .append(" trade.customer_order_id, trade.vendor_order_id, trade.order_goods_id,")
                .append(" trade.settle_status, trade.allowed_settle_amount, trade.organization_id, trade.organization_name,")
                .append(" trade.summary, trade.direction, SUM(trade.amount) AS amount, SUM(trade.freight) AS freight,")
                .append(" trade.platform_rate, trade.interest_rate, trade.other_rate, trade.settle_ids, trade.platform_organization_id,")
                .append(" trade.platform_organization_name,targetTrade.settle_status AS target_settle_status, targetTrade.payment_type AS paymentType, ")
                .append(" GROUP_CONCAT(DISTINCT apply.NUMBER ) AS invoice_number, GROUP_CONCAT(DISTINCT apply.code) AS code, apply.DATE AS createdTime")
                .append(" FROM "+JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_DETAIL)+" detail_bill ")
                .append(" LEFT JOIN ")
                //发票明细已核销的金额
                .append(" (SELECT detail.invoice_detail_bill_id invoice_detail_bill_id,SUM(detail.total) total FROM "+JdbcTemplateUtils.getTableName(ModelConst.T_SETTLE_DETAIL)+" detail")
                .append("    LEFT JOIN "+JdbcTemplateUtils.getTableName(ModelConst.T_SETTLE)+" settle ON settle.ID = detail.settle_id AND detail.deleted = 0 WHERE settle.statuss <> 'Returned' GROUP BY detail.invoice_detail_bill_id)  ")
                .append("  settle_detail ON settle_detail.invoice_detail_bill_id = detail_bill.ID ")
                //交易
                .append(" LEFT JOIN "+JdbcTemplateUtils.getTableName(ModelConst.T_TRADE)+" trade ON detail_bill.trade_id = trade.ID AND trade.deleted = 0")
                //发票申请单
                .append(" LEFT JOIN "+JdbcTemplateUtils.getTableName(ModelConst.T_INVOICE_APPLY)+ " apply ON detail_bill.invoice_apply_id = apply.ID AND apply.deleted = 0")
                //采购交易对应的客户结算状态和付款方式
                .append(" LEFT JOIN ( SELECT target_order_goods_id, direction, settle_status, payment_type FROM "+JdbcTemplateUtils.getTableName(ModelConst.T_TRADE)+" WHERE direction = 'Sale' ) targetTrade")
                .append(" ON targetTrade.target_order_goods_id = trade.order_goods_id ")
                .append(" WHERE ( settle_detail.invoice_detail_bill_id IS NULL OR settle_detail.total < detail_bill.total ) ")
                .append(" AND apply.statuss = 'Done' AND trade.settle_status <> 'Done' AND trade.direction = 'Purchase' ");
        if(StringUtils.isNotBlank(query.getId())){//交易ID
            sql.append(" and trade.id = :tradeId");
            mapBuilder.put("tradeId", query.getId());
        }
        if (StringUtils.isNotBlank(query.getInvoice_status())){//交易开票状态
            sql.append(" and trade.invoice_status = :invoice_status");
            mapBuilder.put("invoice_status", query.getInvoice_status());
        }
        if (StringUtils.isNotBlank(query.getSettle_status())) {//交易结算状态
            sql.append(" and trade.settle_status = :settle_status");
            mapBuilder.put("settle_status", query.getSettle_status());
        }
        if (StringUtils.isNotBlank(query.getInvoice_number())) {//发票号码
            sql.append(" and apply.number = :number");
            mapBuilder.put("number", query.getInvoice_number());
        }
        if (StringUtils.isNotBlank(query.getCustomer_order_id())) {//客户订单ID
            sql.append(" and trade.customer_order_id = :customer_order_id");
            mapBuilder.put("customer_order_id", query.getCustomer_order_id());
        }
        if (StringUtils.isNotBlank(query.getVendor_order_id())) {//供应商订单ID
            sql.append(" and trade.vendor_order_id = :vendor_order_id");
            mapBuilder.put("vendor_order_id", query.getVendor_order_id());
        }
        if (StringUtils.isNotBlank(query.getOrder_goods_id())) {//交易订单商品ID
            sql.append(" and trade.order_goods_id in (:order_goods_id)");
            mapBuilder.put("order_goods_id", query.getOrder_goods_id().split(";"));
        }
        if (StringUtils.isNotBlank(query.getOrganization_name())) {//组织名称
            sql.append(" and trade.organization_name like :organization_name");
            mapBuilder.put("organization_name", "%".concat(query.getOrganization_name()).concat("%"));
        }
        //是否代购
        if (null != query.getBusiness_type()) {
            sql.append(" and trade.business_type = :business_type");
            mapBuilder.put("business_type", query.getBusiness_type());
        }
        //是否转采
        if (null != query.getTransfer_purchase()) {
            sql.append(" and trade.transfer_purchase = :transfer_purchase");
            mapBuilder.put("transfer_purchase", query.getTransfer_purchase());
        }
        //客户是否回款
        if(query.getTarget_settle_statuss() != null){
            sql.append(" and targetTrade.settle_status = :target_settle_status");
            mapBuilder.put("target_settle_status", query.getTarget_settle_statuss());
        }
        //客户回款方式
        if(query.getTarget_payment_type() != null){
            sql.append(" and targetTrade.payment_type = :target_payment_type");
            mapBuilder.put("target_payment_type", query.getTarget_payment_type());
        }
        //对应平台组织
        if(!CollectionUtils.isEmpty(query.getPlatform_organization_id())){
            sql.append(" and JSON_UNQUOTE(trade.platform_organization_id -> '$.id') in (:platform_organization_id)");
            mapBuilder.put("platform_organization_id", query.getPlatform_organization_id());
        }
        return sql.toString();
    }

    @Path("createAdvanceSettle")
    @POST
    @Operation(summary = "平台销售收款管理-平台收款单-新增",description = "平台销售收款管理-新增平台收款单",tags = CUSTOM_SERVICE)
    public SingleResponse createAdvanceSettle(SettleInvoice settleInvoice){
        Assert.isTrue(settleInvoice.getType() != null,"支付类型不能为空");
        settleInvoice.setConfirm_member_id(RequestContext.getCorpLoginId())
                .setConfirm_member_name(RequestContext.getLoginRealName())
                .setApply_member_id(RequestContext.getCorpLoginId())
                .setApply_member_name(RequestContext.getLoginRealName());
        settleService.createAdvanceSettle(settleInvoice);
        return SingleResponse.buildSuccess();
    }

    @Path("createAdvanceRefundSettle")
    @POST
    @Operation(summary = "平台销售收款管理-平台收款单-退款",description = "平台销售收款管理-退款按钮",tags = CUSTOM_SERVICE)
    public SingleResponse createAdvanceRefundSettle(SettleRedInvoice settleRedInvoice){
        if(settleRedInvoice.getSettle_id() == null){
            return SingleResponse.buildFailure("0", "原收款单ID不能为空");
        }
        Settle settleReceive = JdbcTemplateUtils.builder(ModelConst.T_SETTLE).selectField("*")
                .eq("id", settleRedInvoice.getSettle_id()).queryForPOJO(Settle.class);
        if(settleReceive == null ){
            return SingleResponse.buildFailure("0", "未获取到相应收款单");
        }
        if(settleRedInvoice.getTotal().compareTo(settleReceive.getTotal().subtract(settleReceive.getRefund_total())) == 1){
            return SingleResponse.buildFailure("0", "退款金额不能大于收款单金额" + settleReceive.getTotal().subtract(settleReceive.getRefund_total()) + "元");
        }
        settleRedInvoice.setApplyMemberId(RequestContext.getCorpLoginId());
        settleRedInvoice.setApply_member_name(RequestContext.getLoginRealName());
        //数据校验
        verifyRefund(settleRedInvoice);

        settleService.refund(settleRedInvoice, settleReceive);

       return SingleResponse.buildSuccess();
    }

    @Path("viewSettleInvoice")
    @POST
    @Operation(summary = "平台采购付款管理-待申请-申请收款",description = "可结算数据展示",tags = CUSTOM_SERVICE)
    public SettleInvoice viewSettleInvoice(SettleApplyQuery query){
        Assert.notNull(query, "申请结算参数不能为空");
        Assert.notNull(query.getApply_type(), "结算申请类型不能为空");
        Assert.isTrue(!CollectionUtils.isEmpty(query.getIds()), "申请结算的ID不能为空");
        return settleService.viewSettleInvoice(query);
    }

    /**
     * 采购付款单申请
     * @param settleInvoice
     * @return
     */
    @Path("createPurchaseSettle")
    @POST
    @Operation(summary = "平台采购付款管理-待申请-申请收款-确认",description = "",tags = CUSTOM_SERVICE)
    public SingleResponse createPurchaseSettle(SettleInvoice settleInvoice){
        Assert.notNull(settleInvoice, "申请付款参数为空");
        Assert.notNull(settleInvoice.getApply_type(), "申请类型不能为空");
        Assert.notNull(settleInvoice.getSubmit(), "创建后是否提交不能为空");
        Assert.notNull(settleInvoice.getSettleInvoiceDetails(), "结算明细不能为空");

        for (SettleInvoiceDetail settleDetail : settleInvoice.getSettleInvoiceDetails()) {
            Assert.notNull(settleDetail.getApply_id(), "申请ID不能为空");
        }
        return transactionTemplate.execute(status -> {
            settleService.createPurchaseSettle(settleInvoice);
            return SingleResponse.buildSuccess();
        });


    }

    /**
     * 采购付款结算单审批通过
     * @param settleIds
     * @return
     */
    public SingleResponse approveAgree(List<String> settleIds){
        settleService.approveAgree(settleIds);
        return SingleResponse.buildSuccess();
    }

    /**
     * 获取结算单详情发票明细
     * @param dto
     * @return
     */
    @Path("getSettleDetailListBySettleId")
    @POST
    @Operation(summary = "结算单详情-发票明细（id字段必传）",description = "id字段必传",tags = CUSTOM_SERVICE)
    public MultiResponse getSettleDetailListBySettleId(Ids dto){
        Assert.notNull(dto.getId(), "结算单ID不能为空");
        String sql = "select settle_id, invoice_apply_id from "+JdbcTemplateUtils.getTableName(ModelConst.T_SETTLE_DETAIL) + " where settle_id = :settle_id group by settle_id, invoice_apply_id";
        List<Map<String, Object>> queryForList = jdbcTemplate.queryForList(sql, Maps.newHashMap("settle_id", dto.getId()));
        return MultiResponse.of(queryForList, queryForList.size());
    }

    @Path("submitSettle")
    @POST
    @Operation(summary = "供应商销售收款-待提交-提交",description = "ids字段必传",tags = CUSTOM_SERVICE)
    public SingleResponse submitSettle(Ids dto){
        Assert.notNull(dto, "提交参数不能为空");
        Assert.notNull(dto.getIds(), "收款单ID不能为空");
        settleService.submit(dto.getIds());
        return SingleResponse.buildSuccess();
    }

    @Path("refundConfirm")
    @POST
    @Operation(summary = "平台结算退款管理-确认退款",description = "ids字段必传",tags = CUSTOM_SERVICE)
    public SingleResponse refundConfirm(Ids dto){
        Assert.notNull(dto.getIds(), "确认退款ID参数不能为空");
        return transactionTemplate.execute(status -> {
                settleService.refundConfirm(dto.getIds());
                return SingleResponse.buildSuccess();
            });
    }

    @Path("refundCancel")
    @POST
    @Operation(summary = "平台结算退款管理-取消退款",description = "ids字段必传",tags = CUSTOM_SERVICE)
    public SingleResponse refundCancel(Ids dto){
        Assert.notNull(dto.getIds(), "确认退款ID参数不能为空");
        settleService.refundCancel(dto.getIds());
        return SingleResponse.buildSuccess();
    }

    @Path("pageWriteOffRecord")
    @POST
    @Operation(summary = "平台销售收款管理-核销记录",description = "平台销售收款管理-核销记录",tags = CUSTOM_SERVICE)
    public MultiResponse<SettleWriteOffRecord> pageWriteOffRecord(SettleQuery settleQuery){
        if(settleQuery == null){
            return MultiResponse.buildFailure("0", "查询条件不能为空");
        }
        if (CollectionUtils.isEmpty(settleQuery.getSale_organization_id())) {
            //TODO 待确认组织ID查询方式
            settleQuery.setSale_organization_id(PlatformConst.PLATFORM_ORGANIZATION_IDS);
        }
        settleQuery.setBusiness_type(Collections.singletonList(SettleBusinessType.SaleReceivable));

        Map<String, Object> paramMap = MapBuilder.create(new HashMap<String, Object>()).build();
        StringBuffer sql = new StringBuffer("select ")
                .append(" settle.id AS id,settle.purchase_organization_name AS purchase_organization_name,")
                .append(" settle.sale_organization_name AS sale_organization_name,")
                .append(" settle.contract, settle.contract_payment_type,")
                .append(" SUM( detail.total ) AS total,")
                .append(" GROUP_CONCAT(DISTINCT apply.NUMBER) AS invoice_number,")
                .append(" detail.createdBy AS confirm_member_name,")
                .append(" apply.offset_id AS offset_id,")
                .append(" max( detail.createdTime ) AS confirm_time")
                .append(" FROM ")
                .append(" i_financialcenter_t_settle_detail AS detail")
                .append(" LEFT JOIN i_financialcenter_t_invoice_apply AS apply ON apply.id = detail.invoice_apply_id")
                .append(" LEFT JOIN i_financialcenter_t_settle as settle on settle.id = detail.settle_id")
                .append(" where detail.deleted = 0 and settle.business_type = 'SaleReceivable'");
        if(RegexUtils.notNull(settleQuery.getId())){
            sql.append(" and settle.id = :settle_id");
            paramMap.put("settle_id", settleQuery.getId());
        }
        if(RegexUtils.notNull(settleQuery.getPurchase_organization_name())){
            sql.append(" and settle.purchase_organization_name like :purchase_organization_name");
            paramMap.put("purchase_organization_name", "%".concat(settleQuery.getPurchase_organization_name()).concat("%"));
        }
        if(StringUtils.isNotBlank(settleQuery.getInvoice_number())){
            sql.append(" and apply.number in (:invoice_number)");
            paramMap.put("invoice_number", settleQuery.getInvoice_number().split(";"));
        }
        if(!CollectionUtils.isEmpty(settleQuery.getStatuss())){
            sql.append(" and settle.statuss in (:statuss)");
            paramMap.put("statuss", settleQuery.getStatuss());
        }
        if(!CollectionUtils.isEmpty(settleQuery.getSale_organization_id())){
            sql.append(" and JSON_UNQUOTE(settle.sale_organization_id -> '$.id') in (:sale_organization_id)");
            paramMap.put("sale_organization_id", settleQuery.getSale_organization_id());
        }
        if(RegexUtils.notNull(settleQuery.getSale_organization_name())){
            sql.append(" and settle.sale_organization_id like :sale_organization_name");
            paramMap.put("sale_organization_name", "%".concat(settleQuery.getSale_organization_name()).concat("%"));
        }

        //TODO 组织筛选
        sql.append(" GROUP BY settle.id, settle.purchase_organization_name,");
        sql.append(" settle.sale_organization_name,detail.createdTime,detail.createdBy, apply.offset_id");
        if(!CollectionUtils.isEmpty(settleQuery.getConfirm_time())){
            sql.append(" having max(detail.createdTime)>= :start");
            sql.append(" and max(detail.createdTime) <= :end");
            paramMap.put("start", settleQuery.getConfirm_time().get(0));
            paramMap.put("end", settleQuery.getConfirm_time().get(1));
        }
        StringBuffer countSql = new StringBuffer("select count(1) COUNT FROM (").append(sql).append(") as temp");
        log.info("countSql = {}, parameters = {}", countSql, JsonUtils.toJson(paramMap));
        Integer count = jdbcTemplate.queryForObject(countSql.toString(),paramMap, Integer.class);
        if(count == 0){
            return MultiResponse.buildSuccess();
        }
        String limit = String.format(" limit %s,%s", (settleQuery.getPageIndex() - 1) * settleQuery.getPageSize(), settleQuery.getPageSize());
        sql.append(" order by confirm_time desc").append(limit);
        log.info("dataSql = {}, parameters = {}", sql, JsonUtils.toJson(paramMap));
        List<SettleWriteOffRecord> list = JdbcTemplateUtils.queryForPOJOList(sql.toString(), paramMap, ModelConst.T_SETTLE, SettleWriteOffRecord.class);
        list.forEach(item -> {
            item.setHaveRedInvoice(StringUtils.isBlank(item.getOffset_id()) ? "否" : "是");
        });
        return MultiResponse.of(list,count);
    }

    /**
     * 平台销售收款管理-平台收款单-修改
     * 因为修改结算单涉及到金蝶凭证，所以只能自定义服务
     * @param settle
     * @return
     */
    @Path("updateSettleBankInfo")
    @POST
    @Operation(summary = "平台销售收款管理-平台收款单-修改",description = "平台销售收款管理-平台收款单-修改",tags = CUSTOM_SERVICE)
    public SingleResponse  updateSettleBankInfo(Settle settle){
        Assert.notNull(settle, "修改参数不能为空");
        Assert.notNull(settle.getId(), "结算单ID不能为空");
        Assert.isTrue(null != settle.getPurchase_name() && !"".equals(settle.getPurchase_name()), "抬头不能为空");
        verifyUpdateSettle(settle);

        StopWatch stopWatch = new StopWatch();
        stopWatch.start("修改结算单的付款抬头和银行信息");

        Settle settleEntity = JdbcTemplateUtils.builder(ModelConst.T_SETTLE).selectField(" * ")
                .eq("id", settle.getId()).queryForPOJO(Settle.class);
        Assert.notNull(settleEntity, "未查询到相应的结算单");

        //替换英文括号为中文括号
        String purchaseName = settle.getPurchase_name();
        if (null != purchaseName) {
            purchaseName = purchaseName.replace("(", "（");
            purchaseName = purchaseName.replace(")", "）");
        }
        MapBuilder<String, Object> mapBuilder = MapBuilder.create(new HashMap<>());
        mapBuilder.put("purchase_name", purchaseName)
                .put("payment_time", settle.getPayment_time())
                .put("type", settle.getType())
                .put("sale_bank_no", settle.getSale_bank_no())
                .put("sale_bank_info", settle.getSale_bank_info())
                .put("id", settleEntity.getId());
        BoServiceUtils.updateMainBo( ModelConst.T_SETTLE, mapBuilder.build());
        // 凭证部分
        //删除凭证
        kingDeeFinanceService.deleteAdvanceSettle(settle.getId());
        //新增收款凭证
        Settle settleData = JdbcTemplateUtils.builder(ModelConst.T_SETTLE).selectField(" * ").eq("id", settle.getId()).queryForPOJO(Settle.class);
        kingDeeFinanceService.createAdvanceSettle(settleData);

        stopWatch.stop();
        String prettyPrint = stopWatch.prettyPrint();
        log.info(prettyPrint);
        return SingleResponse.buildSuccess();
    }


    @Path("settleCancel")
    @POST
    @Operation(summary = "平台销售收款管理-平台收款单-作废",description = "只能单笔作废，只需要传id即可",tags = CUSTOM_SERVICE)
    public SingleResponse settleCancel(Ids ids){
        Assert.isTrue(StringUtils.isNotBlank(ids.getId()), "作废结算单ID不能为空");
        settleService.cancel(ids.getId());
        return SingleResponse.buildSuccess();
    }

    @Path("settlePurchasePayment")
    @POST
    @Operation(summary = "平台采购付款管理-平台付款申请单-确认付款",description = "平台采购付款管理-平台付款申请单-确认付款",tags = CUSTOM_SERVICE)
    public SingleResponse settlePurchasePayment(List<SettlePayment> paymentList){
        Assert.isTrue(paymentList != null && paymentList.size()>0, "结算付款数据不能为空");
        for (SettlePayment payment : paymentList){
            Assert.notNull(payment.getId(), "付款时结算ID不能为空");
            Assert.notNull(payment.getType(), "付款类型不能为空");
        }
        return transactionTemplate.execute(status -> {
            settleService.settlePurchasePayment(paymentList);
            return SingleResponse.buildSuccess();
        });

    }

    /**
     * 平台采购付款管理-已付款-取消付款
     * @param dto
     * @return
     */
    @Path("paymentCannel")
    @POST
    @Operation(summary = "平台采购付款管理-已付款-取消付款",description = "可以批量取消，传值ids。如无异常直接展示返回的结果即可",tags = CUSTOM_SERVICE)
    public String paymentCannel(Ids dto){
        Assert.isTrue(!CollectionUtils.isEmpty(dto.getIds()), "取消付款参数ids不能为空");
        return transactionTemplate.execute(status -> settleService.paymentCannel(dto.getIds()));

    }

    /**
     * 供应商删除结算单
     * @param dto
     * @return
     */
    @Path("deleteSettle")
    @POST
    @Operation(summary = "供应商收款管理-取消申请",description = "只需要传id",tags = CUSTOM_SERVICE)
    public SingleResponse deleteSettle(Ids dto){
        if(dto.getId() == null){
            return SingleResponse.buildFailure("-1", "要删除的结算单ID不能为空");
        }
        settleService.delete(dto.getId());
        return SingleResponse.buildSuccess();
    }

    /**
     * 平台采购付款管理-平台付款申请单-关闭结算
     * @param dto
     * @return
     */
    @Path("closeSettle")
    @POST
    @Operation(summary = "平台采购付款管理-平台付款申请单-关闭结算",description = "可以批量取消，传值ids。如无异常直接展示返回的结果即可",tags = CUSTOM_SERVICE)
    public String closeSettle(Ids dto){
        Assert.isTrue(!CollectionUtils.isEmpty(dto.getIds()), "取消付款参数ids不能为空");
        return settleService.close(dto.getIds());
    }

    /**
     * 平台销售收款管理-待核销-核销-确定
     */
    @Path("writeOffSettle")
    @POST
    @Operation(summary = "平台销售收款管理-待核销-核销-确定",description = "参数参照原固买",tags = CUSTOM_SERVICE)
    public SingleResponse writeOffSettle(SettleInvoice settleInvoice){
        Assert.isTrue(settleInvoice.getApply_type() == SettleApplyType.Invoice, "只能按发票类型核销");
        Assert.notNull(settleInvoice.getId(), "核销的结算单ID不能为空");
        List<SettleInvoiceDetail> settleInvoiceDetailList = settleInvoice.getSettleInvoiceDetails();
        if(CollectionUtils.isEmpty(settleInvoiceDetailList)){
            return SingleResponse.buildFailure("-1", "发票核销明细不能为空");
        }
        List<String> applyIds = settleInvoiceDetailList.stream().map(SettleInvoiceDetail::getApply_id).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(applyIds)){
            return SingleResponse.buildFailure("-1", "核销的发票ID不存在");
        }
        return transactionTemplate.execute(status -> {
            settleService.writeOffSettle(settleInvoice);
            return SingleResponse.buildSuccess();
        });

    }

    /**
     * 取消核销
     */
    @Path("writeOffSettleCancel")
    @POST
    @Operation(summary = "取消核销",description = "结算单取消核销，按结算单取消只需要传结算单ID，按发票取消核销需传发票ID",tags = CUSTOM_SERVICE)
    public SingleResponse writeOffSettleCancel(WriteOffCancelIds cancelIds){
        Assert.notNull(cancelIds, "取消核销的参数不能为空");
        return transactionTemplate.execute(status -> {
            settleService.writeOffSettleCancel(cancelIds);
            return SingleResponse.buildSuccess();
        });

    }

    @Path("exportSettleReceive")
    @POST
    @Operation(summary = "平台收款管理-导出收款单",description = "平台收款管理-导出收款单",tags = CUSTOM_SERVICE)
    public SingleResponse exportSettleReceive(FinanceReportDto dto){
        Assert.notNull(dto.getReportType().getId(), "导出报表类型异常");
        Assert.notNull(dto.getReportName(), "exportName不能为空");
        Assert.isTrue(dto.getIds().size()==1, "请选择单条收款记录导出");
        List<Map<String, Object>> dataMap = new ArrayList<>();
        Settle settle = settleService.loadById(dto.getIds().get(0));
        if (ObjectUtils.isEmpty(settle)){
            dataMap.add(new HashMap<>());
        }else{
            List<SettleDetail> settleDetailList = JdbcTemplateUtils.builder(ModelConst.T_SETTLE_DETAIL).selectField(" * ")
                    .eq("settle_id", settle.getId())
                    .queryForPOJOList(SettleDetail.class);
            if (CollectionUtils.isEmpty(settleDetailList)){
                Map<String, Object> map = new HashMap<>();
                map.put("id", settle.getId());
                map.put("paymentTime", DateUtils.format(settle.getConfirm_time(), DateUtils.TIMESTAMP_PATTERN));
                map.put("purchaseOrganizationName", settle.getPurchase_organization_name());
                map.put("saleOrganizationName", settle.getSale_organization_name());
                map.put("purchaseBankInfo", settle.getSale_bank_info());
                map.put("purchaseBankNo", settle.getSale_bank_no());
                map.put("purchaseBankAccount", settle.getSale_bank_account());
                map.put("purchaseMemo", settle.getSale_memo());
                dataMap.add(map);
            }else{
                for (SettleDetail settleDetail : settleDetailList){
                    Map<String, Object> map = new HashMap<>();
                    map.put("id", settle.getId());
                    map.put("paymentTime", DateUtils.format(settle.getConfirm_time(), DateUtils.TIMESTAMP_PATTERN));
                    map.put("purchaseOrganizationName", settle.getPurchase_organization_name());
                    map.put("saleOrganizationName", settle.getSale_organization_name());
                    map.put("purchaseBankInfo", settle.getSale_bank_info());
                    map.put("purchaseBankNo", settle.getSale_bank_no());
                    map.put("purchaseBankAccount", settle.getSale_bank_account());
                    map.put("purchaseMemo", settle.getSale_memo());
                    map.put("name", settleDetail.getName());
                    map.put("modelSpec", settleDetail.getModel_spec());
                    map.put("total", settleDetail.getTotal());
                    dataMap.add(map);
                }
            }
        }
        ReportUtils.exportReport(dto.getReportName(),dto.getReportType().getId(), dataMap);
        return SingleResponse.buildSuccess();
    }
    @Path("exportSettlePay")
    @POST
    @Operation(summary = "平台收款管理-导出付款单",description = "平台收款管理-导出付款单",tags = CUSTOM_SERVICE)
    public SingleResponse exportSettlePay(FinanceReportDto dto){
        Assert.notNull(dto.getReportType().getId(), "导出报表类型异常");
        List<SettlePayReport> dataMap = new ArrayList<>();
        List<Settle> settleList = settleService.loadListByIds(dto.getIds());
        if (CollectionUtils.isEmpty(settleList)){
            dataMap.add(SettlePayReport.builder().build());
        }else{
            List<SettleDetail> settleDetailList = JdbcTemplateUtils.builder(ModelConst.T_SETTLE_DETAIL).selectField(" * ")
                    .in("settle_id", settleList.stream().map(Settle::getId).collect(Collectors.toList()))
                    .queryForPOJOList(SettleDetail.class);

            for (Settle settle : settleList){
                List<SettleDetail> mappingDetailList = settleDetailList.stream().filter(t -> t.getSettle_id().equals(settle.getId())).collect(Collectors.toList());
                BigDecimal total = CalculatorUtils.sum(mappingDetailList,BiFunctionConst.settleDetailTotalFun);

                //获取客户订单、供应商订单
                List<Trade> tradeOrderIdsList = JdbcTemplateUtils.builder(ModelConst.T_TRADE).selectField(" vendor_order_id, customer_order_id")
                        .in("id", mappingDetailList.stream().map(SettleDetail::getTrade_id).collect(Collectors.toList()))
                        .queryForPOJOList(Trade.class);
                String vendorOrderIds = String.join(",", tradeOrderIdsList.stream().map(Trade::getVendor_order_id).collect(Collectors.toSet()));
                String customerOrderIds = String.join(",", tradeOrderIdsList.stream().map(Trade::getCustomer_order_id).collect(Collectors.toSet()));

                SettleExtendsAttr settleExtendsAttr = ObjectMapperUtils.fromJSON(settle.getExtends_attr(), SettleExtendsAttr.class);
                dataMap.add(SettlePayReport.builder()
                        .id(settle.getId())
                        .printCount(settleExtendsAttr.getPrintCount()==null ? 1 : settleExtendsAttr.getPrintCount())
                        .vendorOrderIds(vendorOrderIds)
                        .number(settle.getInvoice_number())
                        .applyTime(DateUtils.format(settle.getApply_time(), DateUtils.TIMESTAMP_PATTERN))
                        .purchaseMemo(settle.getPurchase_memo())
                        .saleOrganizationName(settle.getSale_organization_name())
                        .saleBankInfo(settle.getSale_bank_info())
                        .saleBankNo(settle.getSale_bank_no())
                        .total(total)
                        .freight(0d)
                        .platform(settle.getPlatform())
                        .interest(settle.getInterest())
                        .amount(settle.getTotal())
                        .customerOrderIds(customerOrderIds)
                        .approvalReason(settleExtendsAttr.getApprovalReason())
                        .purchaseOrganizationName(settle.getPurchase_organization_name())
                        .build());
            }
        }
        ReportUtils.exportReport(dto.getReportName()==null?"v3_payment_pay_report":dto.getReportName(),dto.getReportType().getId(), dataMap.stream().map(BeanUtil::beanToMap).collect(Collectors.toList()));
        return SingleResponse.buildSuccess();
    }
    @Path("exportPageWriteOffRecord")
    @POST
    @Operation(summary = "平台销售收款管理-核销记录-导出",tags = CUSTOM_SERVICE)
    public SingleResponse exportPageWriteOffRecord(SettleQuery settleQuery){
        settleQuery.setPageSize(500);
        MultiResponse<SettleWriteOffRecord> response = this.pageWriteOffRecord(settleQuery);
        List<Map<String, Object>> dataMap = new ArrayList<>();
        response.getData().forEach(e->{
            Map<String, Object> map = new HashMap<>();
            map.put("id", e.getId());
            map.put("time", DateUtils.format(e.getConfirm_time(), DateUtils.TIMESTAMP_PATTERN));
            map.put("amount", e.getTotal());
            map.put("invoiceNumber", e.getInvoice_number());
            map.put("haveRedInvoice", e.getHaveRedInvoice());
            map.put("confirmMemberName", e.getConfirm_member_name());
            map.put("purchaseOrganizationName", e.getPurchase_organization_name());
            map.put("saleOrganizationName", e.getSale_organization_name());
            dataMap.add(map);
        });
        ReportUtils.exportReport("settle_write_off_record_report","xlsx", dataMap);
        return SingleResponse.buildSuccess();
    }

    /**
     * 修改结算单验证
     *
     * @param settle
     */
    public void verifyUpdateSettle(Settle settle) {
        String businessType = settle.getBusiness_type();
        if (SettleBusinessType.SaleReceivable.name().equals(businessType)) {
            Assert.isTrue(org.apache.commons.lang.StringUtils.isNotBlank(settle.getPurchase_name()), "采购方付款抬头不能为空");
            Assert.notNull(settle.getPayment_time(), "收款日期不能为空");
            Assert.notNull(settle.getType(), "付款方式不能为空");
            Assert.isTrue(org.apache.commons.lang.StringUtils.isNotBlank(settle.getSale_bank_no()), "收款银行账号不能为空");
            Assert.isTrue(org.apache.commons.lang.StringUtils.isNotBlank(settle.getSale_bank_info()), "收款开户行不能为空");
        } else if (SettleBusinessType.SalePayment.name().equals(businessType)) {
            Assert.notNull(settle.getType(), "付款方式不能为空");
            Assert.notNull(settle.getPayment_time(), "付款日期不能为空");
            Assert.isTrue(RegexUtils.notNull(settle.getPurchase_bank_info()), "采购收款开户行不能为空");
            Assert.isTrue(RegexUtils.notNull(settle.getPurchase_bank_no()), "采购收款账号不能为空");
        } else if (SettleBusinessType.PurchasePayment.name().equals(businessType)) {
            Assert.notNull(settle.getType(), "付款方式不能为空");
            Assert.notNull(settle.getPayment_time(), "付款日期不能为空");

        } else {
            Assert.notNull(settle.getType(), "付款方式不能为空");
            Assert.notNull(settle.getPayment_time(), "收款日期不能为空");
        }
    }



    /**
     * 创建反向结算单验证
     *
     * @param settleRedInvoice
     */
    public void verifyRefund(SettleRedInvoice settleRedInvoice) {
        Assert.notNull(settleRedInvoice.getTotal(), "退款金额不能为空");
        Assert.isTrue(settleRedInvoice.getTotal().compareTo(BigDecimal.ZERO) > 0, "退款金额不正确");
        Assert.notNull(settleRedInvoice, "退款信息不能为空");
        Assert.isTrue(null != settleRedInvoice.getApplyMemberId() && RegexUtils.notNull(settleRedInvoice.getApply_member_name()), "申请人信息不能为空");

        Assert.notNull(settleRedInvoice.getType(), "支付类型不能为空");

        Assert.notNull(settleRedInvoice.getPurchase_organization_id(), "采购方组织id不能为空");
        Assert.notNull(settleRedInvoice.getSale_organization_id(), "销售方组织id不能为空");
        Assert.notNull(settleRedInvoice.getPurchase_organization_name(), "采购方组织名称不能为空");
        Assert.notNull(settleRedInvoice.getSale_organization_name(), "销售方组织名称不能为空");
        Assert.isTrue(!settleRedInvoice.getSale_organization_id().equals(settleRedInvoice.getPurchase_organization_id()), "付款组织和收款组织不能相同");

        //平台采购退款，需要知道采购方的银行（供应商退给平台）
        //平台销售退款，需要知道采购方的银行（平台退给客户）
        Assert.isTrue(RegexUtils.notNull(settleRedInvoice.getPurchase_bank_info()), "采购收款开户行不能为空");
        Assert.isTrue(RegexUtils.notNull(settleRedInvoice.getPurchase_bank_no()), "采购收款账号不能为空");
    }

}
